﻿using OfficeClip.OpenSource.StyleFix.Drivers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using OfficeClip.OpenSource.StyleFix;
using System.Collections.Generic;

namespace StyleFixUnitTest
{
    
    
    /// <summary>
    ///This is a test class for SpacingRulesTest and is intended
    ///to contain all SpacingRulesTest Unit Tests
    ///</summary>
    [TestClass()]
    public class SpacingRulesTest
    {
        private TestContext testContextInstance;
        private SpacingRules target;
        private SAObject saObject;
        private List<SAObject> saObjects;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        public SpacingRulesTest()
        {
            target = new SpacingRules();
            target.ForceAllow = true;
            saObject = new SAObject(string.Empty, 1, 1, string.Empty, false);
        }

        /// <summary>
        ///A test for SA1000_KeywordsMustBeSpacedCorrectly
        ///</summary>
        [TestMethod()]
        public void SA1000_KeywordsMustBeSpacedCorrectlyTest()
        {
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1000";
            saObjects.Add(saObject);
            // test catch
            SFWorkingLine workingLine = new SFWorkingLine(1, "catch(", false, saObjects);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "catch (", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // test sizeof
            workingLine = new SFWorkingLine(1, "sizeof (", false, saObjects);
            workingLines.Add(workingLine);
            workingLineExpected = new SFWorkingLine(1, "sizeof(", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // test new
            workingLine = new SFWorkingLine(1, "new [", false, saObjects);
            workingLines.Add(workingLine);
            workingLineExpected = new SFWorkingLine(1, "new[", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // run code
            target.SA1000_KeywordsMustBeSpacedCorrectly(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line);
            Assert.AreEqual(workingLinesExpected[1].Line, workingLines[1].Line);
            Assert.AreEqual(workingLinesExpected[2].Line, workingLines[2].Line);            
        }

        /// <summary>
        ///A test for SA1001_CommasMustBeSpaceCorrectly
        ///</summary>
        [TestMethod()]
        public void SA1001_CommasMustBeSpaceCorrectlyTest()
        {
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1001";
            saObjects.Add(saObject);
            // test comma followed by a single space
            SFWorkingLine workingLine = new SFWorkingLine(1, "void xyz(arg1,arg2)", false, saObjects);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "void xyz(arg1, arg2)", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // test comma preceded by a white space
            workingLine = new SFWorkingLine(1, "void xyz(arg1 , arg2)", false, saObjects);
            workingLines.Add(workingLine);
            workingLineExpected = new SFWorkingLine(1, "void xyz(arg1, arg2)", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // run code
            target.SA1001_CommasMustBeSpaceCorrectly(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line);
            Assert.AreEqual(workingLinesExpected[1].Line, workingLines[1].Line);
        }

        /// <summary>
        ///A test for SA1002_SemicolonsMustBeSpaceCorrectly
        ///</summary>
        [TestMethod()]
        public void SA1002_SemicolonsMustBeSpaceCorrectlyTest()
        {
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1002";
            saObjects.Add(saObject);
            // test semicolon followed by a single space
            SFWorkingLine workingLine = new SFWorkingLine(1, "void xyz(arg1, arg2);x = 3", false, saObjects);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "void xyz(arg1, arg2); x = 3", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // test semicolon preceded by a white space
            workingLine = new SFWorkingLine(1, "void xyz(arg1, arg2) ; x = 3", false, saObjects);
            workingLines.Add(workingLine);
            workingLineExpected = new SFWorkingLine(1, "void xyz(arg1, arg2); x = 3", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // run code
            target.SA1002_SemicolonsMustBeSpaceCorrectly(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line);
            Assert.AreEqual(workingLinesExpected[1].Line, workingLines[1].Line);
        }

        /// <summary>
        ///A test for SA1003_SymbolsMustBeSpaceCorrectly
        ///</summary>
        [TestMethod()]
        public void SA1003_SymbolsMustBeSpaceCorrectlyTest()
        {
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1003";
            saObjects.Add(saObject);
            // no space before and after the operator
            SFWorkingLine workingLine = new SFWorkingLine(1, "a= b+ c", false, saObjects);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "a = b + c", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
             // run code
            target.SA1003_SymbolsMustBeSpaceCorrectly(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line);
        }

        /// <summary>
        ///A test for SA1004_DocumentationLinesMustBeginWithSingleSpace
        ///</summary>
        [TestMethod()]
        public void SA1004_DocumentationLinesMustBeginWithSingleSpaceTest()
        {
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1004";
            saObjects.Add(saObject);
            // no space before and after the operator
            SFWorkingLine workingLine = new SFWorkingLine(1, "///A", false, saObjects);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(2, "///   A", false, saObjects);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(3, "///\tA", false, saObjects);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "/// A", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(2, "/// A", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(3, "/// A", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // run code
            target.SA1004_DocumentationLinesMustBeginWithSingleSpace(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line);
            Assert.AreEqual(workingLinesExpected[1].Line, workingLines[1].Line);
            Assert.AreEqual(workingLinesExpected[2].Line, workingLines[2].Line);
        }
        /// <summary>
        ///A test for SA1005_SingleLineCommentsMustBeginWithSingleSpace
        ///</summary>
        [TestMethod()]
        public void SA1005_SingleLineCommentsMustBeginWithSingleSpaceTest()
        {
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1005";
            saObjects.Add(saObject);
            // No space before the comment
            SFWorkingLine workingLine = new SFWorkingLine(1, "//A single line comment", false, saObjects);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "// A single line comment", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // too many spaces before the comment
            workingLine = new SFWorkingLine(1, "//     A single line comment", false, saObjects);
            workingLines.Add(workingLine);
            workingLineExpected = new SFWorkingLine(1, "// A single line comment", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // run code
            target.SA1005_SingleLineCommentsMustBeginWithSingleSpace(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line);
            Assert.AreEqual(workingLinesExpected[1].Line, workingLines[1].Line);
        }

        /// <summary>
        ///A test for SA1009_ClosingParenthesisMustBeSpacedCorrectly
        ///</summary>
        [TestMethod()]
        public void SA1009_ClosingParenthesisMustBeSpacedCorrectlyTest()
        {
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1009";
            saObjects.Add(saObject);
            List<SAObject> noViolations = new List<SAObject>();
            // Case 1: The closing parenthesis should not be preceded by a whitespace
            SFWorkingLine workingLine = new SFWorkingLine(1, "if (a == 3 )", false, saObjects);
            workingLines.Add(workingLine);
            // Case 2: The closing parenthesis should not be followed by a whitespace if there is a ; ( ) [ ] ; ,
            workingLine = new SFWorkingLine(1, "(a == 3 ) )", false, saObjects);
            workingLines.Add(workingLine);
            // Case 3: The closing parenthesis must not be followed by a whitespace after a cast
            workingLine = new SFWorkingLine(1, "(string) )", false, saObjects);
            workingLines.Add(workingLine);

            // Case 4: New Line
            workingLine = new SFWorkingLine(1, "    }", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(2, "    );", false, saObjects);
            workingLines.Add(workingLine);
            // Case 5: Case 4 Exception
            workingLine = new SFWorkingLine(1, "// A Comment", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(2, "    );", false, saObjects);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            // Case 1 expected value
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "if (a == 3)", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // Case 2 expected value
            workingLineExpected = new SFWorkingLine(2, "(a == 3))", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // Case 3 expected value
            workingLineExpected = new SFWorkingLine(3, "(string))", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // Case 4 expected value
            workingLineExpected = new SFWorkingLine(3, "    });", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // Case 5 expected value
            workingLineExpected = new SFWorkingLine(3, "// A Comment", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(3, ");", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // run code
            target.SA1009_ClosingParenthesisMustBeSpacedCorrectly(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line, @"Case 1 Failed");
            Assert.AreEqual(workingLinesExpected[1].Line, workingLines[1].Line, @"Case 2 Failed");
            Assert.AreEqual(workingLinesExpected[2].Line, workingLines[2].Line, @"Case 3 Failed");
            Assert.AreEqual(workingLinesExpected[3].Line, workingLines[3].Line, @"Case 4 Failed");
            Assert.AreEqual(workingLinesExpected[4].Line, workingLines[4].Line, @"Case 4 Failed");
            Assert.AreEqual(workingLinesExpected[5].Line, workingLines[5].Line, @"Case 4 Failed");
        }

        /// <summary>
        ///A test for SA1010_OpeningSquareBracketsMustBeSpacedCorrectly
        ///</summary>
        [TestMethod()]
        public void SA1010_OpeningSquareBracketsMustBeSpacedCorrectlyTest()
        {
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1010";
            saObjects.Add(saObject);
            // preceded by whitespace
            SFWorkingLine workingLine = new SFWorkingLine(1, "int a [32];", false, saObjects);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "int a[32];", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // followed by whitespace
            workingLine = new SFWorkingLine(1, "int a[ 32];", false, saObjects);
            workingLines.Add(workingLine);
            workingLineExpected = new SFWorkingLine(1, "int a[32];", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // run code
            target.SA1010_OpeningSquareBracketsMustBeSpacedCorrectly(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line);
            Assert.AreEqual(workingLinesExpected[1].Line, workingLines[1].Line);
        }

        /// <summary>
        ///A test for SA1012_OpeningCurlyBracketsMustBeSpacedCorrectly
        ///</summary>
        [TestMethod()]
        public void SA1012_OpeningCurlyBracketsMustBeSpacedCorrectlyTest()
        {
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1012";
            saObjects.Add(saObject);
            // preceded by whitespace
            SFWorkingLine workingLine = new SFWorkingLine(1, "int a {32};", false, saObjects);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "int a { 32};", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // followed by whitespace
            workingLine = new SFWorkingLine(1, "int a{ 32};", false, saObjects);
            workingLines.Add(workingLine);
            workingLineExpected = new SFWorkingLine(1, "int a { 32};", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // run code
            target.SA1012_OpeningCurlyBracketsMustBeSpacedCorrectly(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line);
            Assert.AreEqual(workingLinesExpected[1].Line, workingLines[1].Line);
        }

        /// <summary>
        ///A test for SA1013_ClosingCurlyBracketsMustBeSpacedCorrectly
        ///</summary>
        [TestMethod()]
        public void SA1013_ClosingCurlyBracketsMustBeSpacedCorrectlyTest()
        {
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1013";
            saObjects.Add(saObject);
            // preceded by whitespace
            SFWorkingLine workingLine = new SFWorkingLine(1, "int a {32};", false, saObjects);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "int a {32 };", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // followed by whitespace
            workingLine = new SFWorkingLine(1, "int a { 32 }return;", false, saObjects);
            workingLines.Add(workingLine);
            workingLineExpected = new SFWorkingLine(1, "int a { 32 } return;", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // run code
            target.SA1013_ClosingCurlyBracketsMustBeSpacedCorrectly(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line);
            Assert.AreEqual(workingLinesExpected[1].Line, workingLines[1].Line);
        }

        /// <summary>
        ///A test for SA1027_TabsMustNotBeUsed
        ///</summary>
        [TestMethod()]
        public void SA1027_TabsMustNotBeUsedTest()
        {
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1027";
            saObjects.Add(saObject);
            // no space before and after the operator
            SFWorkingLine workingLine = new SFWorkingLine(1, "\t// comment", false, saObjects);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "    // comment", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            // run code
            target.SA1027_TabsMustNotBeUsed(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line);
        }
    }
}
